package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionReplyAddDto;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionReplyPageQuery;
import com.tianji.learning.domain.query.ReplyAdminPageQuery;
import com.tianji.learning.domain.vo.QuestionReplyVo;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.learning.enums.QuestionStatus.UN_CHECK;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author hc
 * @since 2024-08-25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final UserClient userClient;
    private final InteractionQuestionMapper questionMapper;

    /**
     * <h1>新增回答或者评论</h1>
     *
     * @param replyAddDto
     */
    @Override
    @Transactional
    public void saveReply(QuestionReplyAddDto replyAddDto) {
        Long userId = UserContext.getUser();
        if (ObjectUtil.isEmpty(replyAddDto)) {
            throw new BizIllegalException("新增回答参数异常");
        }
        InteractionReply interactionReply = BeanUtil.toBean(replyAddDto, InteractionReply.class);
        interactionReply.setUserId(userId);
//        新增
        save(interactionReply);
//        判断是否是回答
        Boolean result = ObjectUtil.isAllEmpty(replyAddDto.getAnswerId()
                , replyAddDto.getTargetReplyId()
                , replyAddDto.getTargetUserId()) ? addReplyTimes(replyAddDto) : changeQuestionLatestAnswerId(interactionReply.getId(), replyAddDto);
        if (!result) {
            throw  new BizIllegalException("新增出错");
        }
//        是否是学生提交
        if (ObjectUtil.isNotEmpty(replyAddDto.getIsStudent())&& BooleanUtil.isTrue(replyAddDto.getIsStudent())) {
            InteractionQuestion bean = BeanUtil.toBean(replyAddDto, InteractionQuestion.class);
//            累加问题表回答次数
            boolean success = questionMapper.update(bean, new LambdaUpdateWrapper<InteractionQuestion>().
                    eq(InteractionQuestion::getId, replyAddDto.getQuestionId())
                    .setSql("answer_times = answer_times+1 ")) > 0;
            if (!success) throw  new BizIllegalException("累加问题表回答次数出错");
        }
    }
    /**
     * <h1>修改最近异常回答的id</h1>
     *
     * @param replyAddDto
     * @return
     */
    private Boolean changeQuestionLatestAnswerId(Long latestAnswerId, QuestionReplyAddDto replyAddDto) {
        InteractionQuestion bean = BeanUtil.toBean(replyAddDto, InteractionQuestion.class);
        return questionMapper.update(bean, new LambdaUpdateWrapper<InteractionQuestion>()
                .eq(InteractionQuestion::getId, replyAddDto.getQuestionId())
                .set(InteractionQuestion::getLatestAnswerId, latestAnswerId)
                .set(InteractionQuestion::getStatus, UN_CHECK)
                .setSql("answer_times = answer_times+1")) >0 ;
    }

    /**
     * <h1>累加回答下的评论次数</h1>
     *
     * @param replyAddDto
     * @return
     */
    private Boolean addReplyTimes(QuestionReplyAddDto replyAddDto) {
        return  lambdaUpdate().eq(InteractionReply::getId,replyAddDto.getAnswerId())
                .setSql("reply_times = reply_times+1").update();

    }

    /**
     * <h1>分页查询回答和评论列表</h1>
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionReplyVo> queryPageReply(QuestionReplyPageQuery pageQuery) {
        Long answerId = pageQuery.getAnswerId();
        Long questionId = pageQuery.getQuestionId();
//        判断参数是否错误
        if (ObjectUtil.isEmpty(answerId) && ObjectUtil.isEmpty(questionId))
            throw new BizIllegalException("评论分页查询接口参数错误");
//分页查询
        Page<InteractionReply> ReplyPage = lambdaQuery()
                .eq(ObjectUtil.isNotEmpty(questionId), InteractionReply::getQuestionId, questionId)
                .eq(ObjectUtil.isNotEmpty(answerId), InteractionReply::getAnswerId, answerId)
                .eq(InteractionReply::getHidden, false)
                .page(pageQuery.toMpPage("liked_times", false));
        List<InteractionReply> records = ReplyPage.getRecords();
//       收集用户iD 和 回复的用户目标用户id 集合
        Set<Long> userIDs = new HashSet<>(records.size());
        Set<Long> targetUserIds = new HashSet<>(records.size());
        Set<Long> questionIds = new HashSet<>(records.size());
        records.forEach(v -> {
            userIDs.add(v.getUserId());
            targetUserIds.add(v.getTargetUserId());
            questionIds.add(v.getQuestionId());
        });
//        将关于用户的字段收集
        Map<Long, UserDTO> userDTOMap = userClient.queryUserByIds(userIDs).stream()
                .collect(Collectors.toMap(UserDTO::getId, Function.identity()));
//        收集别评论的用户昵称
        Map<Long, String> targetUserNames = userClient.queryUserByIds(targetUserIds).stream()
                .collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

        Map<Long, Long> questionMap = questionIds.stream().collect(Collectors.toMap(Long::longValue,Long::longValue));
        List<QuestionReplyVo> list = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
//            转换Bean
            QuestionReplyVo replyVo = BeanUtil.toBean(record, QuestionReplyVo.class);
//            补充id字段
            if (ObjectUtil.isNotEmpty(questionMap)) {
                replyVo.setId(questionMap.get(record.getQuestionId()));
            }
//            填充用户信息字段
            if (ObjectUtil.isNotEmpty((userDTOMap))) {
                UserDTO userDTO = userDTOMap.get(record.getUserId());
//                匿名用户不填充
                if (BooleanUtil.isFalse(record.getAnonymity())) {
                    replyVo.setUserName(userDTO.getName());
                    replyVo.setUserIcon(userDTO.getIcon());
                }
//                填充最近一次回答用户昵称
                if (ObjectUtil.isNotEmpty(targetUserNames)) {
                    replyVo.setTargetUserName(targetUserNames.get(record.getTargetUserId()));
                }
            }
            list.add(replyVo);
        }
        return PageDTO.of(ReplyPage, list);
    }



    /**
     * 管理端分页查询回答或评论列表
     *
     * @param pageQuery 查询条件
     * @return
     */
    @Override
    public PageDTO<ReplyVO> queryByPage(ReplyAdminPageQuery pageQuery) {
        //1、分页查询回复
        Page<InteractionReply> pageResult = lambdaQuery()
                .eq(InteractionReply::getAnswerId, ObjectUtils.isNotEmpty(pageQuery.getAnswerId()) ? pageQuery.getAnswerId() : 0L)
                .eq(ObjectUtils.isNotEmpty(pageQuery.getQuestionId()), InteractionReply::getQuestionId, pageQuery.getQuestionId())
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionReply> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        //2、获取到回答者id和回复的目标用户id
        List<Long> userIds = new ArrayList<>();
        for (InteractionReply record : records) {
            userIds.add(record.getUserId());
            userIds.add(record.getTargetUserId());
        }

        //3、获取到用户信息
        List<UserDTO> userInfoS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(userInfoS)) {
            userMap = userInfoS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }

        //4、开始封装返回结果
        List<ReplyVO> vos = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            ReplyVO replyVO = BeanUtil.toBean(record, ReplyVO.class);
            if (ObjectUtils.isNotEmpty(userMap.get(record.getUserId()))) {
                replyVO.setUserName(userMap.get(record.getUserId()).getName());
                replyVO.setUserIcon(userMap.get(record.getUserId()).getIcon());
            }
            if (ObjectUtils.isNotEmpty(userMap.get(record.getTargetUserId()))) {
                replyVO.setTargetUserName(userMap.get(record.getTargetUserId()).getName());
            }
            vos.add(replyVO);
        }
        return PageDTO.of(pageResult, vos);
    }

    /**
     * 管理端显示或隐藏评论 练习四
     *
     * @param id     回答或者回答的回复id
     * @param hidden 是否隐藏
     */
    @Override
    public void showOrHidden(Long id, Boolean hidden) {
        //1、更新回答本身
        lambdaUpdate()
                .set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getId, id)
                .update();
        //2、更新该回答下的回复
        lambdaUpdate()
                .set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getAnswerId, id)
                .update();

    }
}
